/**
 * MQTT 通信API模块 - 基于成功示例重写
 * 使用标准 mqtt 库，支持H5和APP端，专注于项目功能
 */

// 导入标准 mqtt 库
var mqtt = require('mqtt/dist/mqtt.js')
// 导入设备状态管理器
import deviceStore from '@/store/deviceStore.js'
// 导入用户store用于获取用户ID
import { store as userStore } from '@/uni_modules/uni-id-pages/common/store.js'

/**
 * MQTT 连接配置
 */
const MQTT_CONFIG = {
	host: 'ka1e5a49.ala.cn-hangzhou.emqxsl.cn',
	port: 8084,
	auth: {
		username: 'linyuchi',
		password: 'adSd@@4d'
	}
}

/**
 * MQTT 客户端封装
 */
class MyMQTTClient {
	constructor() {
		this.client = null
		this.isConnected = false
		this.isConnecting = false  // 添加连接中标志，防止重复连接
		this.subscriptions = new Set() // 记录已订阅的主题
		this.deviceList = [] // 当前监听的设备列表
		this.messageHandlerRegistered = false // 标记message监听器是否已注册
		
		// 订阅时间戳记录，用于过滤订阅后立即返回的离线消息
		this.subscriptionTimestamps = new Map() // deviceSn -> timestamp
		this.ignoreOfflineWindow = 5000 // 订阅后5秒内忽略 reason:disconnect 的离线消息
		
		console.log('[MY-MQTT] MQTT 客户端初始化')
	}

	/**
	 * 连接到 MQTT 服务器
	 * @param {Object} params 连接参数
	 * @returns {Promise} 连接Promise
	 */
	async connect(params = {}) {
		// 检查是否真的连接着（不仅检查状态，还要检查client对象）
		if (this.isConnected && this.client && this.client.connected) {
			console.log('[MY-MQTT] 已连接，跳过重复连接')
			return Promise.resolve('已连接')
		}
		
		// 如果正在连接中,返回等待（不强制重置）
		if (this.isConnecting) {
			console.log('[MY-MQTT] 正在连接中，等待连接完成...')
			// 等待连接完成或超时（最多10秒）
			return new Promise((resolve, reject) => {
				let checkCount = 0
				const checkInterval = setInterval(() => {
					checkCount++
					if (this.isConnected && this.client && this.client.connected) {
						clearInterval(checkInterval)
						console.log('[MY-MQTT] 等待完成，连接已建立')
						resolve('连接成功')
					} else if (checkCount > 20) { // 10秒超时
						clearInterval(checkInterval)
						console.warn('[MY-MQTT] 等待超时，强制重置并重新连接')
						this.isConnecting = false
						// 重新调用connect
						this.connect(params).then(resolve).catch(reject)
					}
				}, 500)
			})
		}
		
		// 如果client存在但未连接，先清理
		if (this.client) {
			console.log('[MY-MQTT] 发现旧连接，先清理')
			try {
				// 移除所有事件监听器,避免内存泄漏
				this.client.removeAllListeners()
				this.client.end(true) // 强制关闭
			} catch (e) {
				console.error('[MY-MQTT] 清理旧连接失败:', e)
			}
			this.client = null
			this.isConnected = false
			this.messageHandlerRegistered = false // 重置监听器标记
		}
		
		// 设置连接中标志
		this.isConnecting = true

		// 生成唯一的clientId（避免多设备/多标签页冲突）
		let defaultClientId = 'Uniapp_'
		// #ifdef H5
		defaultClientId += 'H5_'
		// #endif
		// #ifdef APP-PLUS
		// #ifdef APP-PLUS-IOS
		defaultClientId += 'iOS_'
		// #endif
		// #ifdef APP-PLUS-ANDROID
		defaultClientId += 'Android_'
		// #endif
		// #endif
		// 添加用户ID确保不同用户有唯一ClientId
		const userId = userStore.userInfo?._id || 'anonymous'
		defaultClientId += userId + '_'
		// 添加时间戳（毫秒）+ 4位随机数，确保同一用户多设备也唯一
		defaultClientId += Date.now() + '_' + Math.floor(Math.random() * 10000)

		// 构建连接参数
		const connectParams = {
			clientId: params.clientId || defaultClientId,
			username: params.username || MQTT_CONFIG.auth.username,
			password: params.password || MQTT_CONFIG.auth.password,
			clean: params.clean !== undefined ? params.clean : true
		}
		
		console.log('[MY-MQTT] 🆔 使用ClientId:', connectParams.clientId)

		// 构建连接URL
		let url = ''
		// #ifdef H5
		url = `wss://${MQTT_CONFIG.host}:${MQTT_CONFIG.port}/mqtt`
		// #endif
		// #ifdef APP-PLUS
		url = `wxs://${MQTT_CONFIG.host}:${MQTT_CONFIG.port}/mqtt`
		// #endif

		return new Promise((resolve, reject) => {
			try {
				console.log(`[MY-MQTT] 开始连接: ${url}, ClientId: ${connectParams.clientId}`)
				
				// 使用参考代码中的连接方式
				let options = {
					clientId: connectParams.clientId,
					username: connectParams.username,
					password: connectParams.password,
					clean: connectParams.clean,
					connectTimeout: 600000,
					// 使用clean session避免会话持久化导致多用户消息分发冲突
					cleanSession: true
				}
				
				this.client = mqtt.connect(url, options)

				// 立即注册所有事件监听器（在connect事件触发前）
				// 🔑 关键修复: 防止重复注册message监听器
				if (!this.messageHandlerRegistered) {
					console.log('[MY-MQTT] 🎯 注册message事件监听器 (首次)')
					this.messageHandlerRegistered = true
					
					// 消息接收
					this.client.on('message', (topic, message, packet) => {
						try {
							console.log(`[MY-MQTT] 📨 收到MQTT消息 - Topic: ${topic}`)
							
							let messageStr = ''
							
							// 兼容不同的消息格式
							if (typeof message === 'string') {
								messageStr = message
							} else if (message && message.toString) {
								messageStr = message.toString()
							} else if (packet && packet.payload) {
								messageStr = packet.payload.toString()
							} else {
								console.warn('[MY-MQTT] 无法解析消息内容')
								return
							}
							
							console.log(`[MY-MQTT] 📨 消息内容预览: ${messageStr.substring(0, 200)}`)
							this.handleMessage(topic, messageStr)
						} catch (error) {
							console.error('[MY-MQTT] 消息处理异常:', error)
						}
					})
				} else {
					console.log('[MY-MQTT] ⏭️ 跳过message监听器注册 (已存在)')
					console.log(`[MY-MQTT] 📊 当前message监听器数量: ${this.client.listenerCount('message')}`)
				}

				// 重连
				this.client.on('reconnect', () => {
					console.log('[MY-MQTT] 重新连接中...')
				})

				// 关闭
				this.client.on('close', () => {
					console.log('[MY-MQTT] 连接关闭')
					this.isConnected = false
					deviceStore.mqttConnected = false
				})

				// 离线
				this.client.on('offline', () => {
					console.log('[MY-MQTT] 连接离线')
					this.isConnected = false
					deviceStore.mqttConnected = false
				})

				// 连接成功
				this.client.on('connect', async () => {
					console.log(`[MY-MQTT] 连接成功 - ClientId: ${connectParams.clientId}`)
					console.log(`[MY-MQTT] 📊 message监听器数量: ${this.client.listenerCount('message')}`)
					
					this.isConnected = true
					this.isConnecting = false
					deviceStore.mqttConnected = true
					
					// 重新订阅之前的主题
					if (this.subscriptions.size > 0) {
						const topics = Array.from(this.subscriptions)
						this.subscriptions.clear()
						
						for (const topic of topics) {
							try {
								await this.subscribe(topic)
							} catch (error) {
								console.error(`[MY-MQTT] 重新订阅失败 ${topic}:`, error)
							}
						}
					}
					
					resolve('连接成功')
				})
				
				// 连接错误
				this.client.on('error', (error) => {
					console.error('[MY-MQTT] 连接错误:', error)
					this.isConnected = false
					this.isConnecting = false
					deviceStore.mqttConnected = false
					
					if (this.client) {
						try {
							this.client.removeAllListeners()
							this.client.end(true)
						} catch (e) {
							console.error('[MY-MQTT] 清理连接失败:', e)
						}
						this.client = null
						this.messageHandlerRegistered = false
					}
					
					reject(error)
				})

			} catch (error) {
				console.error('[MY-MQTT] 连接异常:', error)
				reject(error)
			}
		})
	}

	/**
	 * 断开连接
	 */
	disconnect() {
		return new Promise((resolve) => {
			if (this.client == null) {
				console.log('[MY-MQTT] 断开连接: 未连接')
				resolve('未连接')
				return
			}
			
			console.log('[MY-MQTT] 断开连接')
			
			try {
				// 只有在客户端连接时才尝试关闭
				if (this.client.connected) {
					this.client.end(false, () => {
						console.log('[MY-MQTT] 连接已安全关闭')
					})
				} else {
					// 如果已经断开，直接强制关闭
					this.client.removeAllListeners()
					this.client.end(true)
				}
			} catch (error) {
				console.warn('[MY-MQTT] 断开连接时出错:', error)
			}
			
			this.client = null
			this.isConnected = false
			this.messageHandlerRegistered = false
			// 不清空 subscriptions，以便重连后恢复订阅
			// this.subscriptions.clear()
			deviceStore.mqttConnected = false
			resolve('连接终止')
		})
	}

	/**
	 * 订阅主题
	 * @param {String} topic 主题
	 * @param {Number} qos QoS级别
	 */
	subscribe(topic, qos = 1) {
		return new Promise((resolve, reject) => {
			if (this.client == null || !this.isConnected) {
				console.warn(`[MY-MQTT] 订阅失败 - 未连接: ${topic}`)
				resolve('未连接')
				return
			}

			// 如果已经订阅过，跳过重复订阅
			if (this.subscriptions.has(topic)) {
				resolve('已订阅')
				return
			}

			this.client.subscribe(topic, { qos }, (err, res) => {
				if (!err && res && res.length > 0) {
					this.subscriptions.add(topic)
					console.log(`[MY-MQTT] ✅ 订阅成功: ${topic}`)
					console.log(`[MY-MQTT] 📊 订阅响应:`, res)
					console.log(`[MY-MQTT] 📊 当前已订阅主题数: ${this.subscriptions.size}`)
					resolve('订阅成功')
				} else {
					console.error(`[MY-MQTT] 订阅失败: ${topic}`, err, res)
					resolve('订阅失败')
				}
			})
		})
	}

	/**
	 * 取消订阅
	 * @param {String} topic 主题
	 */
	unsubscribe(topic) {
		return new Promise((resolve, reject) => {
			if (this.client == null || !this.isConnected) {
				resolve('未连接')
				console.log('[MY-MQTT] 取消订阅失败: 未连接')
				return
			}

			this.client.unsubscribe(topic, (err) => {
				if (!err) {
					this.subscriptions.delete(topic)
					console.log(`[MY-MQTT] 取消订阅成功: ${topic}`)
					resolve('取消订阅成功')
				} else {
					console.log(`[MY-MQTT] 取消订阅失败: ${topic}`)
					resolve('取消订阅失败')
				}
			})
		})
	}

	/**
	 * 发布消息
	 * @param {String} topic 主题
	 * @param {String|Object} message 消息内容
	 */
	publish(topic, message) {
		return new Promise((resolve, reject) => {
			if (this.client == null || !this.isConnected) {
				console.log('[MY-MQTT] 发布失败: 未连接')
				resolve(false) // 返回 false 表示失败
				return
			}

			const payload = typeof message === 'object' ? JSON.stringify(message) : message
			
			this.client.publish(topic, payload, (err) => {
				if (!err) {
					console.log(`[MY-MQTT] 发布成功: ${topic} - ${payload}`)
					resolve(true) // 返回 true 表示成功
				} else {
					console.log(`[MY-MQTT] 发布失败: ${topic} - ${payload}`)
					resolve(false) // 返回 false 表示失败
				}
			})
		})
	}

	/**
	 * 处理接收到的消息
	 * @param {String} topic 主题
	 * @param {String} messageStr 消息字符串
	 */
	handleMessage(topic, messageStr) {
		try {
			console.log(`[MY-MQTT] 🔍 处理消息 - Topic: ${topic}`)
			
			const deviceSn = this.extractDeviceSnFromTopic(topic)
			if (!deviceSn) {
				console.warn(`[MY-MQTT] 无法从主题中提取设备SN: ${topic}`)
				return
			}
			
			console.log(`[MY-MQTT] 提取设备SN: ${deviceSn}`)
			
			// 处理简化的设备心跳消息（仅在线状态）
			if (topic.includes('/heartbeat')) {
				console.log(`[MY-MQTT] ➡️ 路由到 heartbeat 处理器`)
				this.handleDeviceHeartbeat(deviceSn, messageStr)
			}
			// 处理设备响应消息（统一响应格式）
			else if (topic.includes('/response')) {
				console.log(`[MY-MQTT] ➡️ 路由到 response 处理器`)
				this.handleDeviceResponse(deviceSn, messageStr)
			}
			else {
				console.log(`[MY-MQTT] ❓ 未知主题类型: ${topic}`)
			}
		} catch (error) {
			console.error('[MY-MQTT] 消息处理失败:', error)
		}
	}

	/**
	 * 从主题中提取设备SN
	 * @param {String} topic 主题
	 * @returns {String} 设备SN
	 */
	extractDeviceSnFromTopic(topic) {
		const parts = topic.split('/')
		return parts[2] // /SANDART001/{SN}/heartbeat
	}

	/**
	 * 处理简化的设备心跳消息(仅在线状态)
	 * @param {String} deviceSn 设备SN
	 * @param {String} messageStr 消息字符串
	 */
		handleDeviceHeartbeat(deviceSn, messageStr) {
		try {
			// 修复可能存在的JSON格式问题
			// 有些设备的rssi字段格式不正确，如 "rssi":-4B，需要修正为 "rssi":-4
			let fixedMessageStr = messageStr
			const rssiMatch = messageStr.match(/"rssi"\s*:\s*(-?\d+)([a-zA-Z]+)/)
			if (rssiMatch) {
				console.warn(`[MY-MQTT] 检测到不规范的rssi格式: ${rssiMatch[0]}`)
				fixedMessageStr = messageStr.replace(/"rssi"\s*:\s*(-?\d+)[a-zA-Z]+/, `"rssi":${rssiMatch[1]}`)
			}
			
			const heartbeatData = JSON.parse(fixedMessageStr)
			
			const topicSnNormalized = (deviceSn || '').toLowerCase()
			const messageSnRaw = typeof heartbeatData.sn === 'string' ? heartbeatData.sn.trim() : ''
			const messageSnNormalized = messageSnRaw ? messageSnRaw.toLowerCase() : ''
			const resolvedSn = messageSnNormalized || topicSnNormalized
			
			if (!messageSnRaw) {
				console.warn('[MY-MQTT] 心跳消息缺少sn字段，使用主题SN兜底', {
					topicSn: deviceSn,
					payloadSn: heartbeatData.sn
				})
			} else if (messageSnNormalized !== topicSnNormalized) {
				console.warn('[MY-MQTT] 心跳消息SN与主题不一致', {
					messageSn: messageSnRaw,
					topicSn: deviceSn
				})
			}
			
			if (heartbeatData.online === undefined) {
				console.warn('[MY-MQTT] 心跳消息缺少online字段，跳过更新', {
					topicSn: deviceSn,
					payload: heartbeatData
				})
				return
			}
			
			// 🔥 过滤订阅后立即返回的 disconnect 离线消息
			if (heartbeatData.online === false && heartbeatData.reason === 'disconnect') {
				const subscribeTime = this.subscriptionTimestamps.get(resolvedSn)
				if (subscribeTime) {
					const timeSinceSubscribe = Date.now() - subscribeTime
					if (timeSinceSubscribe < this.ignoreOfflineWindow) {
						console.log(`[MY-MQTT] 🚫 忽略订阅后的初始disconnect消息 (订阅后${timeSinceSubscribe}ms):`, {
							deviceSn: resolvedSn,
							reason: heartbeatData.reason,
							subscribeTime: new Date(subscribeTime).toISOString(),
							currentTime: new Date().toISOString()
						})
						return // 忽略这条消息
					} else {
						console.log(`[MY-MQTT] ⚠️ disconnect消息已超过忽略窗口 (订阅后${timeSinceSubscribe}ms)，将处理:`, {
							deviceSn: resolvedSn,
							reason: heartbeatData.reason
						})
					}
				} else {
					console.log(`[MY-MQTT] ⚠️ 未找到订阅时间戳记录，将处理disconnect消息:`, {
						deviceSn: resolvedSn,
						reason: heartbeatData.reason
					})
				}
			}
			
			// 只更新在线状态和信号强度（resolvedSn 已处理大小写与缺失情况）
			deviceStore.updateDeviceOnlineStatus(resolvedSn, {
				online: heartbeatData.online,
				ts: heartbeatData.ts,
				rssi: heartbeatData.rssi,
				reportedSn: messageSnRaw || null,
				topicSn: deviceSn
			})
		} catch (error) {
			console.error(`[MY-MQTT] 处理设备 ${deviceSn} 心跳失败:`, error)
			console.error(`[MY-MQTT] 原始消息: ${messageStr}`)
		}
	}	/**
	 * 处理设备响应消息（新版统一格式）
	 * @param {String} deviceSn 设备SN
	 * @param {String} messageStr 消息字符串
	 */
	handleDeviceResponse(deviceSn, messageStr) {
		try {
			console.log(`[MY-MQTT] 收到设备 ${deviceSn} 响应消息`)
			console.log(`[MY-MQTT] 原始消息: ${messageStr.substring(0, 500)}`)
			
			// 修复可能存在的JSON格式问题
			let fixedMessageStr = messageStr
			const rssiMatch = messageStr.match(/"rssi"\s*:\s*(-?\d+)([a-zA-Z]+)/)
			if (rssiMatch) {
				console.warn(`[MY-MQTT] 检测到不规范的rssi格式: ${rssiMatch[0]}`)
				fixedMessageStr = messageStr.replace(/"rssi"\s*:\s*(-?\d+)[a-zA-Z]+/, `"rssi":${rssiMatch[1]}`)
			}
			
			const responseData = JSON.parse(fixedMessageStr)
			console.log(`[MY-MQTT] 解析后的响应数据:`, responseData)
			
			// 验证响应数据格式
			if (!responseData.type || !responseData.data) {
				console.warn(`[MY-MQTT] 响应消息格式无效:`, responseData)
				return
			}
			
			// 确保设备SN匹配（不区分大小写）
			// 注意: get_status返回的response消息没有device_sn字段,只能通过主题中的SN来识别
			if (responseData.device_sn && 
			    responseData.device_sn.toLowerCase() !== deviceSn.toLowerCase()) {
				console.warn(`[MY-MQTT] 响应消息设备SN不匹配: 期望 ${deviceSn}, 收到 ${responseData.device_sn}`)
				return
			}
			
			console.log(`[MY-MQTT] 路由响应消息到 DeviceStore, type: ${responseData.type}`)
			// 路由响应消息到 DeviceStore 处理
			deviceStore.handleDeviceResponse(deviceSn, responseData)
			
		} catch (error) {
			console.error(`[MY-MQTT] 处理设备 ${deviceSn} 响应消息失败:`, error)
			console.error(`[MY-MQTT] 原始消息: ${messageStr}`)
		}
	}

	/**
	 * 处理设备状态消息（兼容旧版本格式）
	 * @param {String} deviceSn 设备SN
	 * @param {String} messageStr 消息字符串
	 */
		handleDeviceStatus(deviceSn, messageStr) {
		try {
			const statusData = JSON.parse(messageStr)
			
			// 处理完整的设备状态数据
			const processedStatus = {
				// 基础设备信息
				online: statusData.online,
				sn: statusData.sn,
				ts: statusData.ts,
				heap: statusData.heap,
				version: statusData.ver,
				
				// 图案播放状态
				currentPattern: statusData.pattern ? {
					pattern_id: statusData.pattern.pattern_id,
					progress: statusData.pattern.progress || 0,
					status: statusData.pattern.status || 0, // 0=停止, 1=播放, 2=暂停
					duration: statusData.pattern.duration || 0,
					elapsed_time: statusData.pattern.elapsed_time || 0,
					remaining_time: statusData.pattern.remaining_time || 0,
					started_at: statusData.pattern.started_at,
					estimated_end: statusData.pattern.estimated_end
				} : null,
				
				// 播放控制设置
				playback: statusData.playback ? {
					speed: statusData.playback.speed || 100,
					is_paused: statusData.playback.is_paused || false,
					auto_clear: statusData.playback.auto_clear || true,
					loop_mode: statusData.playback.loop_mode || 'single',
					pause_reason: statusData.playback.pause_reason,
					pause_after_complete: statusData.playback.pause_after_complete,
					pause_duration: statusData.playback.pause_duration,
					clear_before_new: statusData.playback.clear_before_new
				} : null,
				
				// 灯光设置
				lightSettings: statusData.lightSettings ? {
					enabled: statusData.lightSettings.enabled || false,
					mode: statusData.lightSettings.mode || 'constant',
					color: statusData.lightSettings.color || '#FFFFFF',
					brightness: statusData.lightSettings.brightness || 80,
					speed: statusData.lightSettings.speed || 50,
					color_temperature: statusData.lightSettings.color_temperature
				} : null
			}
			
			// 更新完整的设备状态到store
			deviceStore.updateDeviceStatus(deviceSn, processedStatus)
			
		} catch (error) {
			console.error(`[MY-MQTT] 处理设备 ${deviceSn} 状态失败:`, error)
		}
	}

	/**
	 * 启动设备监听（心跳+状态）
	 * @param {Array} deviceList 设备列表
	 */
	async startDeviceMonitoring(deviceList = []) {
		try {
			if (!this.isConnected || !this.client || !this.client.connected) {
				console.warn('[MY-MQTT] MQTT未连接，无法启动设备监听')
				return
			}
			
			// 如果client已连接但标志未更新，同步状态
			if (this.client.connected && !this.isConnected) {
				this.isConnected = true
				deviceStore.mqttConnected = true
			}

			// 先取消旧设备的订阅，避免重复订阅
			if (this.deviceList && this.deviceList.length > 0) {
				await this.stopDeviceMonitoring(this.deviceList)
			}
			
			// 保存新设备列表
			this.deviceList = deviceList

			// 为每个设备订阅心跳和响应主题
			for (const device of deviceList) {
				if (!device.sn) {
					console.warn(`[MY-MQTT] 跳过无SN设备: ${device.device_name}`)
					continue
				}
				
				const topicVariants = this.getTopicVariants(device.sn)
				
			for (const snVariant of topicVariants) {
				// 订阅简化心跳主题（仅在线状态）
				const heartbeatTopic = `/SANDART001/${snVariant}/heartbeat`
				await this.subscribe(heartbeatTopic)
				
				// 记录订阅时间戳，用于过滤订阅后立即返回的离线消息
				// 使用统一的小写SN作为key
				const normalizedSn = snVariant.toLowerCase()
				this.subscriptionTimestamps.set(normalizedSn, Date.now())
				console.log(`[MY-MQTT] 记录订阅时间戳: ${normalizedSn} -> ${Date.now()}`)
				
				// 订阅响应消息主题（统一响应格式）
				const responseTopic = `/SANDART001/${snVariant}/response`
				await this.subscribe(responseTopic)
				
				// 主动请求设备当前状态
				await this.requestDeviceStatus(snVariant)
			}
			}
			
			console.log(`[MY-MQTT] 设备监听设置完成: ${deviceList.length} 个设备`)
		} catch (error) {
			console.error('[MY-MQTT] 启动设备监听失败:', error)
		}
	}

	/**
	 * 主动请求设备当前状态
	 * @param {String} deviceSn 设备SN
	 */
	async requestDeviceStatus(deviceSn) {
		try {
			const command = { cmd: "get_status" }
			const commandTopic = `/SANDART001/${deviceSn}/command`
			await this.publish(commandTopic, command)
		} catch (error) {
			console.error(`[MY-MQTT] 请求设备 ${deviceSn} 状态失败:`, error)
		}
	}

	/**
	 * 停止设备监听
	 * @param {Array} deviceList 要停止监听的设备列表
	 */
	async stopDeviceMonitoring(deviceList = []) {
		try {
			const devicesToStop = deviceList.length > 0 ? deviceList : this.deviceList
			
			for (const device of devicesToStop) {
				if (!device.sn) {
					continue
				}
				const topicVariants = this.getTopicVariants(device.sn)
				for (const snVariant of topicVariants) {
					// 取消订阅心跳、响应主题
					const heartbeatTopic = `/SANDART001/${snVariant}/heartbeat`
					await this.unsubscribe(heartbeatTopic)
					
					const responseTopic = `/SANDART001/${snVariant}/response`
					await this.unsubscribe(responseTopic)
				}
			}
			
			// 如果停止了所有设备，清空设备列表
			if (deviceList.length === 0) {
				this.deviceList = []
			}
		} catch (error) {
			console.error('[MY-MQTT] 停止设备监听失败:', error)
		}
	}

	/**
	 * 根据设备SN生成可能的主题变体（保持原样 + 小写）
	 * @param {String} deviceSn 设备SN
	 * @returns {Array<String>} 主题SN列表
	 */
	getTopicVariants(deviceSn) {
		const variants = []
		const rawSn = (deviceSn || '').trim()
		if (rawSn) {
			variants.push(rawSn)
			const lowerSn = rawSn.toLowerCase()
			if (lowerSn && !variants.includes(lowerSn)) {
				variants.push(lowerSn)
			}
		}
		return variants
	}

	/**
	 * 获取连接状态
	 */
	getConnectionStatus() {
		// 如果正在连接中，也返回true（等待连接完成）
		if (this.isConnecting) {
			return true
		}
		
		// 检查客户端对象是否存在且连接
		if (!this.client) {
			this.isConnected = false
			deviceStore.mqttConnected = false
			return false
		}
		
		// 优先使用内部状态标志
		// 因为在某些平台(如iOS)上,client.connected 可能更新延迟
		if (this.isConnected && this.client.connected === true) {
			return true
		}
		
		// 检查 client.connected 属性
		const clientConnected = this.client.connected === true
		
		// 如果内部标志显示已连接,但 client 显示未连接
		// 可能是状态不同步,以 client 为准并更新状态
		if (this.isConnected && !clientConnected) {
			this.isConnected = false
			deviceStore.mqttConnected = false
			return false
		}
		
		// 如果内部标志显示未连接,但 client 显示已连接
		// 更新内部状态为已连接
		if (!this.isConnected && clientConnected) {
			this.isConnected = true
			deviceStore.mqttConnected = true
			return true
		}
		
		return this.isConnected
	}
}

// 创建全局MQTT客户端实例
const myMqttClient = new MyMQTTClient()

/**
 * 导出API - 兼容原有接口
 */
export default {
	// === 核心连接API ===
	async connect(params = {}) {
		return await myMqttClient.connect(params)
	},

	disconnect() {
		return myMqttClient.disconnect()
	},

	isConnected() {
		return myMqttClient.getConnectionStatus()
	},

	// === 订阅和发布API ===
	async subscribe(params) {
		return await myMqttClient.subscribe(params.topic, params.qos)
	},

	async unsubscribe(params) {
		return await myMqttClient.unsubscribe(params.topic)
	},

	async publish(params) {
		return await myMqttClient.publish(params.topic, params.message)
	},

	// === 设备监听管理API ===
	async startDeviceMonitoring(deviceList) {
		return await myMqttClient.startDeviceMonitoring(deviceList)
	},

	async stopDeviceMonitoring(deviceList) {
		return await myMqttClient.stopDeviceMonitoring(deviceList)
	},

	// === 连接状态管理API ===
	onConnectionChange(callback) {
		// 添加连接状态变化监听
		if (myMqttClient.client) {
			myMqttClient.client.on('connect', () => callback(true))
			myMqttClient.client.on('close', () => callback(false))
			myMqttClient.client.on('offline', () => callback(false))
		}
		// 返回当前连接状态
		callback(myMqttClient.isConnected)
	},

	async subscribeDeviceStatus(deviceSn, messageCallback) {
		const statusTopic = `/SANDART001/${deviceSn}/status`
		
		console.log(`[MY-MQTT API] 订阅设备 ${deviceSn} 状态主题: ${statusTopic}`)
		
		// 订阅状态主题
		const subscribeResult = await myMqttClient.subscribe(statusTopic)
		console.log(`[MY-MQTT API] 订阅结果: ${subscribeResult}`)
		
		// 主动请求当前状态
		console.log(`[MY-MQTT API] 主动请求设备 ${deviceSn} 当前状态`)
		await myMqttClient.requestDeviceStatus(deviceSn)
		
		// 设置消息回调处理 - 增强版本
		if (myMqttClient.client && messageCallback) {
			const originalHandler = myMqttClient.handleMessage.bind(myMqttClient)
			myMqttClient.handleMessage = (topic, messageStr) => {
				// 首先调用原始处理器更新store
				originalHandler(topic, messageStr)
				
				// 然后调用自定义回调
				if (topic === statusTopic) {
					try {
						messageCallback(topic, messageStr)
					} catch (error) {
						console.error(`[MY-MQTT API] 状态回调处理失败:`, error)
					}
				}
			}
		}
		
		return true
	},

	/**
	 * 主动请求设备状态
	 * @param {string} deviceSn 设备SN
	 */
	async requestDeviceStatus(deviceSn) {
		console.log(`[MY-MQTT API] 请求设备 ${deviceSn} 状态`)
		return await myMqttClient.requestDeviceStatus(deviceSn)
	},

	/**
	 * 获取设备完整状态（订阅+请求）
	 * @param {string} deviceSn 设备SN
	 * @param {function} statusCallback 状态更新回调函数
	 */
	async getDeviceFullStatus(deviceSn, statusCallback) {
		try {
			// 1. 订阅状态主题
			const statusTopic = `/SANDART001/${deviceSn}/status`
			await myMqttClient.subscribe(statusTopic)
			console.log(`[MY-MQTT API] 已订阅设备 ${deviceSn} 状态主题`)
			
			// 2. 设置状态回调
			if (statusCallback && typeof statusCallback === 'function') {
				// 保存原始处理函数
				const originalHandler = myMqttClient.handleDeviceStatus.bind(myMqttClient)
				
				// 重写状态处理函数
				myMqttClient.handleDeviceStatus = (sn, messageStr) => {
					// 调用原始处理函数更新store
					originalHandler(sn, messageStr)
					
					// 如果是目标设备，调用回调函数
					if (sn === deviceSn) {
						try {
							const statusData = JSON.parse(messageStr)
							statusCallback(statusData)
						} catch (error) {
							console.error(`[MY-MQTT API] 状态回调执行失败:`, error)
						}
					}
				}
			}
			
			// 3. 主动请求当前状态
			await this.requestDeviceStatus(deviceSn)
			console.log(`[MY-MQTT API] 已请求设备 ${deviceSn} 当前状态`)
			
			return true
		} catch (error) {
			console.error(`[MY-MQTT API] 获取设备 ${deviceSn} 完整状态失败:`, error)
			return false
		}
	},

	// === 设备控制API ===
	async sendDeviceCommand(deviceSn, command) {
		const commandTopic = `/SANDART001/${deviceSn}/command`
		return await myMqttClient.publish(commandTopic, command)
	},

	// === LED灯光控制API ===
	async turnOnLight(deviceSn) {
		const command = { cmd: "ledon" }
		console.log(`[MY-MQTT API] 开启设备 ${deviceSn} LED灯光:`, command)
		return await this.sendDeviceCommand(deviceSn, command)
	},

	async turnOffLight(deviceSn) {
		const command = { cmd: "ledoff" }
		console.log(`[MY-MQTT API] 关闭设备 ${deviceSn} LED灯光:`, command)
		return await this.sendDeviceCommand(deviceSn, command)
	},

	async setLightEffect(deviceSn, mode) {
		const effectValue = this.getModeValue(mode)
		const command = { cmd: "draweffect", value: effectValue }
		console.log(`[MQTT API] 设置设备 ${deviceSn} 灯光效果:`, command)
		return await this.sendDeviceCommand(deviceSn, command)
	},

	async setLightColor(deviceSn, color) {
		const rgb = this.hexToRgb(color)
		const command = { cmd: "drawcolor", r: rgb.r, g: rgb.g, b: rgb.b }
		console.log(`[MQTT API] 设置设备 ${deviceSn} 灯光颜色:`, command)
		return await this.sendDeviceCommand(deviceSn, command)
	},

	getModeValue(mode) {
		const modeMap = {
			'constant': 0,
			'breathing': 1,
			'rainbow': 3,
			'tracking': 10
		}
		return modeMap[mode] || 0
	},

	hexToRgb(hex) {
		const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex)
		return result ? {
			r: parseInt(result[1], 16),
			g: parseInt(result[2], 16),
			b: parseInt(result[3], 16)
		} : { r: 255, g: 255, b: 255 }
	},

	async setLightBrightness(deviceSn, brightness) {
		const brightnessValue = Math.round(brightness * 255 / 100)
		const command = { cmd: "drawbright", value: brightnessValue }
		console.log(`[MQTT API] 设置设备 ${deviceSn} 灯光亮度:`, command)
		return await this.sendDeviceCommand(deviceSn, command)
	},

	async setLightSpeed(deviceSn, speed) {
		const command = { cmd: "drawspeed", value: speed }
		console.log(`[MQTT API] 设置设备 ${deviceSn} 灯光速度:`, command)
		return await this.sendDeviceCommand(deviceSn, command)
	},
	async sendLightControl(deviceSn, lightConfig) {
		const command = { cmd: "lightcontrol", ...lightConfig }
		console.log(`[MY-MQTT API] 发送灯光控制命令到设备 ${deviceSn}:`, command)
		return await this.sendDeviceCommand(deviceSn, command)
	},

	// === 绘图控制API ===
	async startDrawing(deviceSn, pattern = null) {
		const command = pattern ? { cmd: "start", pattern } : { cmd: "start" }
		console.log(`[MY-MQTT API] 开始绘图设备 ${deviceSn}:`, command)
		return await this.sendDeviceCommand(deviceSn, command)
	},

	async playDrawing(deviceSn, pattern = null) {
		const command = pattern ? { cmd: "play", pattern } : { cmd: "play" }
		console.log(`[MY-MQTT API] 播放绘图设备 ${deviceSn}:`, command)
		return await this.sendDeviceCommand(deviceSn, command)
	},
	async stopDrawing(deviceSn) {
		const command = { cmd: "stop" }
		console.log(`[MY-MQTT API] 停止绘图设备 ${deviceSn}:`, command)
		return await this.sendDeviceCommand(deviceSn, command)
	},

	async nextPattern(deviceSn) {
		const command = { cmd: "next" }
		console.log(`[MY-MQTT API] 切换到下一个图案 ${deviceSn}:`, command)
		return await this.sendDeviceCommand(deviceSn, command)
	},

	async prevPattern(deviceSn) {
		const command = { cmd: "prev" }
		console.log(`[MY-MQTT API] 切换到上一个图案 ${deviceSn}:`, command)
		return await this.sendDeviceCommand(deviceSn, command)
	},

	async sendPlaybackControl(deviceSn, playbackConfig) {
		const command = { cmd: "playbackcontrol", ...playbackConfig }
		console.log(`[MY-MQTT API] 发送播放控制设置到设备 ${deviceSn}:`, command)
		return await this.sendDeviceCommand(deviceSn, command)
	},

	/**
	 * 设置播放模式
	 * @param {string} deviceSn 设备序列号
	 * @param {string} mode 播放模式: 'sequential'(顺序), 'random'(随机), 'single_loop'(单曲循环)
	 * @returns {Promise<boolean>}
	 */
	async setPlaybackMode(deviceSn, mode) {
		const command = { cmd: "playbackcontrol", playback_mode: mode }
		console.log(`[MY-MQTT API] 设置播放模式 ${deviceSn}:`, mode)
		return await this.sendDeviceCommand(deviceSn, command)
	},

		// === 播放列表控制API ===
	/**
	 * 发送播放列表命令（支持分页）
	 * @param {string} deviceSn 设备序列号
	 * @param {string} action 操作类型
	 * @param {Array<string|object>} patterns 图案列表（支持字符串数组或对象数组）
	 * @param {Object} pageInfo 分页信息 { page, total_pages }
	 * @returns {Promise<boolean>}
	 */
	async sendPlaylistCommand(deviceSn, action, patterns = [], pageInfo = null) {
		// 统一转换为字符串数组格式以节约内存
		const patternFiles = patterns.map(p => {
			if (typeof p === 'string') {
				return p  // 已经是字符串,直接使用
			} else if (p && typeof p === 'object') {
				// 从对象中提取文件名
				return p.pattern_file || p.file_name || p.fileName || String(p)
			}
			return String(p)
		})
		
		const commandData = {
			action,
			patterns: patternFiles
		}
		
		// 如果有分页信息，添加到命令中
		if (pageInfo && pageInfo.page && pageInfo.total_pages) {
			commandData.page = pageInfo.page
			commandData.total_pages = pageInfo.total_pages
		}
		
		const command = {
			cmd: "playlist",
			data: commandData
		}
		
		console.log(`[MY-MQTT API] 发送播放列表命令到设备 ${deviceSn}:`, command)
		return await this.sendDeviceCommand(deviceSn, command)
	},

	/**
	 * 分页发送播放列表
	 * @param {string} deviceSn 设备序列号
	 * @param {string} action 操作类型
	 * @param {Array<string|object>} patterns 图案列表
	 * @param {number} pageSize 每页大小，默认10个
	 * @param {number} delayMs 每页之间的延迟（毫秒），默认100ms
	 * @returns {Promise<{success: boolean, totalPages: number, sentPages: number}>}
	 */
	async sendPlaylistWithPagination(deviceSn, action, patterns = [], pageSize = 10, delayMs = 100) {
		try {
			// 转换为文件名数组
			const patternFiles = patterns.map(p => {
				if (typeof p === 'string') {
					return p
				} else if (p && typeof p === 'object') {
					return p.pattern_file || p.file_name || p.fileName || String(p)
				}
				return String(p)
			})
			
			const totalPatterns = patternFiles.length
			const totalPages = Math.ceil(totalPatterns / pageSize)
			
			console.log(`[MY-MQTT API] 开始分页发送播放列表: 总数=${totalPatterns}, 每页=${pageSize}, 总页数=${totalPages}`)
			
			if (totalPages === 0) {
				console.warn(`[MY-MQTT API] 播放列表为空，无需发送`)
				return { success: true, totalPages: 0, sentPages: 0 }
			}
			
			let sentPages = 0
			
			// 分页发送
			for (let page = 1; page <= totalPages; page++) {
				const startIndex = (page - 1) * pageSize
				const endIndex = Math.min(startIndex + pageSize, totalPatterns)
				const pagePatterns = patternFiles.slice(startIndex, endIndex)
				
				console.log(`[MY-MQTT API] 发送第 ${page}/${totalPages} 页, 包含 ${pagePatterns.length} 个图案`)
				
				// 发送这一页
				await this.sendPlaylistCommand(
					deviceSn, 
					action, 
					pagePatterns,
					{ page, total_pages: totalPages }
				)
				
				sentPages++
				
				// 如果不是最后一页，等待一段时间再发送下一页
				if (page < totalPages && delayMs > 0) {
					await new Promise(resolve => setTimeout(resolve, delayMs))
				}
			}
			
			console.log(`[MY-MQTT API] 播放列表分页发送完成: ${sentPages}/${totalPages} 页`)
			
			return {
				success: true,
				totalPages,
				sentPages
			}
			
		} catch (error) {
			console.error(`[MY-MQTT API] 播放列表分页发送失败:`, error)
			throw error
		}
	},

	// 播放列表便捷方法
	async addToPlaylist(deviceSn, patterns) {
		return await this.sendPlaylistCommand(deviceSn, "add", patterns)
	},

	async setPlaylist(deviceSn, patterns, pageSize = 10) {
		// 始终使用分页方式推送，无论图案数量多少
		console.log(`[MY-MQTT API] setPlaylist 始终使用分页方式，图案数=${patterns.length}, 每页=${pageSize}`)
		return await this.sendPlaylistWithPagination(deviceSn, "set", patterns, pageSize)
	},

	async removeFromPlaylist(deviceSn, patterns) {
		return await this.sendPlaylistCommand(deviceSn, "remove", patterns)
	},

	async clearPlaylist(deviceSn) {
		return await this.sendPlaylistCommand(deviceSn, "clear", [])
	},

	async getPlaylist(deviceSn) {
		return await this.sendPlaylistCommand(deviceSn, "get", [])
	},

	// === 工具方法 ===
	getModeValue(mode) {
		const modeMap = {
			'constant': 0,
			'breathing': 1,
			'rainbow': 3,
			'tracking': 10
		}
		return modeMap[mode] || 0
	},

	getModeFromValue(value) {
		const valueMap = {
			0: 'constant',
			1: 'breathing',
			3: 'rainbow',
			10: 'tracking'
		}
		return valueMap[value] || 'constant'
	},

	hexToRgb(hex) {
		const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex)
		return result ? {
			r: parseInt(result[1], 16),
			g: parseInt(result[2], 16),
			b: parseInt(result[3], 16)
		} : { r: 255, g: 255, b: 255 }
	},

	rgbToHex(r, g, b) {
		return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1).toUpperCase()
	},

	parseRgbString(rgbString) {
		if (!rgbString) return { r: 255, g: 255, b: 255 }
		
		const parts = rgbString.split(',').map(part => parseInt(part.trim()))
		if (parts.length === 3 && parts.every(part => !isNaN(part))) {
			return { r: parts[0], g: parts[1], b: parts[2] }
		}
		return { r: 255, g: 255, b: 255 }
	},

	// === 客户端实例 ===
	client: myMqttClient
}